// Copyright 2011 Jim Xochellis
// Licensed under the Apache License, Version 2.0 
// (http://www.apache.org/licenses/LICENSE-2.0)
 
#include "prof_events.h"

#include <vector>
#include <cassert>
#include <cstdlib>

//---------------------------------------------------------------

namespace generic_profiling
{

class default_event_handler : public event_handler
{
public:
	default_event_handler()
		: event_counters_(profiling_events_count, 0) {}

	virtual void handle_event(unsigned the_event)
	{
		if ( (the_event > 0) && ((size_t)the_event < event_counters_.size()) )
			++event_counters_[the_event];
	}

	size_t get_event_counter(unsigned the_event)
	{
		if ( (the_event > 0) && ((size_t)the_event < event_counters_.size()) )
			return event_counters_[the_event];
		else
			return 0;
	}

	void reset()
	{
		std::fill(event_counters_.begin(), event_counters_.end(), 0);
	}

protected:
	std::vector<size_t> event_counters_;
};

//---------------------------------------------------------------

static event_handler *s_event_handler_ptr = new default_event_handler;
static bool s_profiling_is_enabled = true;

void set_event_handler(event_handler *handler)
{
	if (handler != s_event_handler_ptr)
	{
		delete s_event_handler_ptr;
		s_event_handler_ptr = handler;
	}
}

event_handler *get_event_handler()
{
	return s_event_handler_ptr;
}

void dispatch_event(unsigned event_type)
{
	if ( s_profiling_is_enabled && (s_event_handler_ptr != NULL) )
		s_event_handler_ptr->handle_event(event_type);
}

//---------------------------------------------------------------

void enable_profiling(bool enable)
{
	s_profiling_is_enabled = enable;
}

bool is_profiling_enabled()
{
	return s_profiling_is_enabled;
}

size_t get_event_counter(unsigned the_event)
{
	default_event_handler *default_handler_ptr = dynamic_cast<default_event_handler *>(s_event_handler_ptr);

	assert(default_handler_ptr != NULL);
	if (default_handler_ptr != NULL)
		return default_handler_ptr->get_event_counter(the_event);
	else
		return 0;
}

void reset_event_counters()
{
	default_event_handler *default_handler_ptr = dynamic_cast<default_event_handler *>(s_event_handler_ptr);

	assert(default_handler_ptr != NULL);
	if (default_handler_ptr != NULL)
		default_handler_ptr->reset();
}

const char *get_event_name(unsigned the_event)
{
	static const char *counter_names[] =
	{
		"",
		"value_pure_creation",
		"value_copy_creation",
		"value_move_creation",
		"value_copy_assignment",
		"value_move_assignment",
		"value_simple_comparison",
		"value_arithmetic_event",
		"value_swap_event",

		"iterator_pure_creation",
		"iterator_copy_creation",
		"iterator_copy_assignment",
		"iterator_simple_comparison",
		"iterator_dereference",
		"iterator_simple_step",
		"iterator_long_step",
		"iterator_arithmetic",
	};

	const size_t counter_names_count = sizeof (counter_names) / sizeof (*counter_names);

	if (the_event < counter_names_count)
		return counter_names[the_event];
	else
		return "";
}

//---------------------------------------------------------------

} //namespace generic_profiling
